/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { SourceFile } from 'ts-morph';
import { ImportManager } from '../shared/ImportManager';
import {
  ClassAnalysis,
  ClassDetails,
  DependencySource,
  DeserializationMode,
  GenerationContext,
  InterfaceAnalysis,
  InterfaceDetails,
  ITaskContext,
  Logger,
  PropertyAnalysis,
  PropertyGenerationInfo,
  PropertyKind,
  StringConstants,
  TypeDependency,
  TypeKind,
  TypeStructure
} from '../../..';
import { HandlebarsTemplateEngine } from '../../../template/HandlebarsTemplateEngine';
import { ConfigManager } from '../../../utils/ConfigManager';
import { ClassAnalyzer } from '../../../analyzers/ClassAnalyzer';
import { TempSerializerGenerator } from './TempSerializerGenerator';
import { TypeHandlerRegistry } from '../../../handlers';
import SerializationPathUtil from '../../../utils/SerializationPathUtil';

export class SerializerGenerator {
  private readonly importManager: ImportManager;
  private readonly templateEngine: HandlebarsTemplateEngine;
  private readonly registry = TypeHandlerRegistry.getInstance();

  constructor(importManager: ImportManager) {
    this.importManager = importManager;
    this.templateEngine = new HandlebarsTemplateEngine();
  }

  generate(sourceFile: SourceFile, result: ClassAnalysis | InterfaceAnalysis,
    context: ITaskContext): GenerationContext | string {
    // 检查是否使用自定义序列化器
    if (result.decorators?.serializable?.with) {
      sourceFile.addStatements(
        this.generateBuiltinSerializerRegistrationForSupplementary(context, result as ClassAnalysis));
      // 使用自定义序列化器，仅生成注册语句
      return this.generateCustomSerializerRegistration(result as ClassAnalysis);
    }

    // 1. 注册必要的导入
    this.registerImports(result);

    // 2. 使用模板引擎生成代码
    const templateContext: GenerationContext = {
      class: result,
      properties: this.propertyAnalysisToPropertyGenerationInfo(result.properties),
      serialNameConstant: this.generateSerialNameConstant(result, context)
    };
    const templateMode = result.decorators?.serializable?.deserializationMode
      ? result.decorators.serializable?.deserializationMode
      : ConfigManager.getInstance().getConfig().deserializationMode;

    const generatedCode = this.templateEngine.render(templateMode, templateContext);

    // 3. 将生成的代码添加到源文件
    sourceFile.addStatements(generatedCode);

    return templateContext;
  }

  /**
   * 生成注册语句
   * @param sourceFile
   * @param content
   */
  generateRegistration(sourceFile: SourceFile, content: GenerationContext | string): void {
    // 添加到源文件
    if (typeof content === 'string') {
      sourceFile.addStatements(content);
    } else {
      const generatedCode = this.templateEngine.renderRegister(content);
      sourceFile.addStatements(generatedCode);
    }
  }

  private registerImports(result: ClassAnalysis | InterfaceAnalysis): void {
    Logger.debug('SerializerGenerator', 'registerImports', `注册导入: ${result.className}`);

    // 收集所有需要的内置序列化器
    const requiredBuiltinSerializers = this.getAllRequiredSerializers(result.properties);

    // 基础导入 + 动态内置序列化器导入
    this.importManager.registerCoreImports([
      'Serializer', 'SerialDescriptor', 'buildClassSerialDescriptor',
      'Encoder', 'Decoder', 'registerAutoGeneratedSerializerEntry', 'ObjectUtils',
      'registerAutoGeneratedSerializerEntryProviderForSupplementary',
      ...requiredBuiltinSerializers
    ]);

    this.registerDecoratorsImports(result);

    const deserializationMode =
      result.decorators?.serializable?.deserializationMode ||
      ConfigManager.getInstance().getConfig().deserializationMode;

    // PreciseTemplate 需要的额外导入
    if (deserializationMode === DeserializationMode.STRICT) {
      this.importManager.registerCoreImports([
        'SerializationError', 'SerializationErrorCodes',
        'TypeUtils', 'DecodedElementIndex', 'TurboTransLogger'
      ]);
    }

    if (result.generics.isGeneric) {
      this.importManager.registerCoreImports(['BaseSerializerFactory']);
    }

    this.registerPropertyImports(result);

    this.registerInheritancePropertyImports(result);
  }

  private registerDecoratorsImports(result: ClassAnalysis | InterfaceAnalysis): void {
    // 注册装饰器导入
    result.ownProperties.forEach(property => {
      if (property.decorators?.serialName) {
        this.importManager.registerCoreImports(['SerialName']);
      }
      if (property.decorators?.isRequired) {
        this.importManager.registerCoreImports(['Required']);
      }
      if (property.decorators?.isTransient) {
        this.importManager.registerCoreImports(['Transient']);
      }
    });
  }

  private registerInheritancePropertyImports(result: ClassAnalysis | InterfaceAnalysis): void {
    const baseClass = result.inheritance.baseClassAnalysis;
    // 注册继承类导入
    if (baseClass && baseClass.sourceFilePath !== result.sourceFilePath) {
      // 导入继承的类
      this.importManager.registerCustomTypeImport(baseClass.sourceFilePath, baseClass.className);

      // 导入继承类中属性需要的导入
      baseClass.ownProperties.forEach(property => {
        this.execInheritancePropertyImports(property.type.dependencies);
      });
    }
  }

  private execInheritancePropertyImports(dependencies: TypeDependency[]): void {
    dependencies.forEach((dependency: TypeDependency) => {
      const source = dependency.source;
      if (source.type === 'local') {
        this.importManager.registerCustomTypeImport(source.sourceFilePath!, dependency.typeName);

        const classDetails = dependency.details as ClassDetails;
        const tempClassAnalysis = ClassAnalyzer.analyzeClass(classDetails.classDecl);

        if (!tempClassAnalysis.decorators.serializable) {
          TempSerializerGenerator.getInstance().generateSerializer(tempClassAnalysis);
        }

        const serializerName = classDetails.isGeneric ? StringConstants.SERIALIZER_FACTORY :
          StringConstants.SERIALIZER;

        if (tempClassAnalysis.decorators.serializable) {
          this.importManager.registerCustomTypeImport(
            source.sourceFilePath!,
            `${dependency.typeName}${serializerName}`
          );
        }
      }
    });
  }

  private registerPropertyImports(result: ClassAnalysis | InterfaceAnalysis): void {
    // 根据属性注册序列化器导入
    for (const property of result.properties) {
      if (property.decorators?.isTransient) {
        continue;
      }

      if (property.decorators?.with) {
        if (this.containsGenericType(property.type)) {
          this.importManager.registerCoreImports(['WithEntrySerializer']);
        } else {
          this.importManager.registerCoreImports(['WithEntryContextualSerializer']);
        }
      }

      // 注册属性相关的序列化器导入
      this.execPropertyImports(property.type.dependencies, !!property.decorators?.with);
    }
  }

  private execPropertyImports(dependencies: TypeDependency[], hasWithParam: boolean): void {
    dependencies.forEach((dependency: TypeDependency) => {
      this.processDependency(dependency, hasWithParam);
    });
  }

  private processDependency(dependency: TypeDependency, hasWithParam: boolean): void {
    const source = dependency.source;

    // 提前返回，减少嵌套
    if (source.type !== 'imported' && source.type !== 'local') {
      return;
    }

    if (source.type === 'imported') {
      this.importManager.registerCustomTypeImport(source.sourceFilePath!, dependency.typeName);
    }

    // 根据类型种类分别处理
    switch (dependency.typeKind) {
      case TypeKind.CLASS:
        this.processClassDependency(dependency, source, hasWithParam);
        break;

      case TypeKind.INTERFACE:
        this.processInterfaceDependency(dependency, hasWithParam);
        break;
    }
  }

  private processClassDependency(dependency: TypeDependency, source: DependencySource, hasWithParam: boolean): void {
    const classDetails = dependency.details as ClassDetails;
    const tempClassAnalysis = ClassAnalyzer.analyzeClass(classDetails.classDecl);

    if (!tempClassAnalysis.decorators.serializable) {
      TempSerializerGenerator.getInstance().generateSerializer(tempClassAnalysis);
    }

    const serializerName = classDetails.isGeneric ? StringConstants.SERIALIZER_FACTORY :
      StringConstants.SERIALIZER;

    if (tempClassAnalysis.decorators.serializable) {
      this.handleSerializableClass(dependency, source, serializerName);
    } else {
      if (hasWithParam) {
        // 有自定义序列化器，无需关注这个导入了
        return;
      }
      // 从 tempSerializer 目录（index.ets）导入
      this.importManager.registerTempSerializerImport(`${dependency.typeName}${serializerName}`);
    }
  }

  private handleSerializableClass(dependency: TypeDependency, source: DependencySource, serializerName: string): void {
    if (source.type === 'imported') {
      this.importManager.registerCustomTypeImport(
        source.sourceFilePath!,
        `${dependency.typeName}${serializerName}`
      );
    }
  }

  private processInterfaceDependency(dependency: TypeDependency, hasWithParam: boolean): void {
    if (hasWithParam) {
      // 有自定义序列化器，无需关注这个导入了
      return;
    }
    const interfaceDetails = dependency.details as InterfaceDetails;
    const tempClassAnalysis = ClassAnalyzer.analyzeInterface(interfaceDetails.interfaceDecl);
    TempSerializerGenerator.getInstance().generateSerializer(tempClassAnalysis);

    const serializerName = (dependency.details as ClassDetails).isGeneric ? StringConstants.SERIALIZER_FACTORY :
      StringConstants.SERIALIZER;

    // 从 tempSerializer 目录（index.ets）导入
    this.importManager.registerTempSerializerImport(`${dependency.typeName}${serializerName}`);
  }

  private generateCustomSerializerRegistration(result: ClassAnalysis): string {
    this.importManager.registerCoreImports(['registerAutoGeneratedSerializerEntry']);

    const customSerializer = result.decorators.serializable!.with;
    return `registerAutoGeneratedSerializerEntry(${result.className}, ${customSerializer});`;
  }

  private generateBuiltinSerializerRegistrationForSupplementary(context: ITaskContext, result: ClassAnalysis): string {
    this.importManager.registerCoreImports(['registerAutoGeneratedSerializerEntryProviderForSupplementary']);
    const serialNameConstant = this.generateSerialNameConstant(result, context);

    const customSerializer = result.decorators.serializable!.with;
    return `const ${result.className}_SERIAL_NAME = '${serialNameConstant}';\n
    registerAutoGeneratedSerializerEntryProviderForSupplementary(${result.className}_SERIAL_NAME, () => [${result.className}, ${customSerializer}]);`;
  }

  private getAllRequiredSerializers(properties: PropertyAnalysis[]): string[] {
    const requiredSerializers = new Set<string>();

    properties.forEach(property => {
      // 递归检查所有属性中需要的序列化器
      const nestedSerializers = this.analyzeNestedSerializers(property.type);
      nestedSerializers.forEach(serializer => requiredSerializers.add(serializer));
    });

    return Array.from(requiredSerializers);
  }

  private analyzeNestedSerializers(structure: TypeStructure): string[] {
    const requiredSerializers = new Set<string>();

    // 递归分析函数
    const analyzeType = (type: TypeStructure): void => {
      // 容错机制：跳过 UNKNOWN 类型
      if (type.kind === PropertyKind.UNKNOWN) {
        return;
      }

      if (type.kind === PropertyKind.GENERIC) {
        return; // 跳过类和泛型，这俩没有内置序列化器
      }
      // 获取当前类型的序列化器名称
      const handler = this.registry.getHandlerForKind(type.kind);
      const metadata = handler.getSerializerMetadata(type);
      Logger.debug(`Analyzing type ${type.sourceText}, metadata ${metadata.name}`);
      if (type.kind !== PropertyKind.OBJECT) { // Object类型需要判断泛型类型对应序列化器
        requiredSerializers.add(metadata.name);
      }

      // 递归分析泛型参数
      if (type.args && type.args.length > 0) {
        type.args.forEach(arg => analyzeType(arg));
      }

      // 递归分析联合类型成员
      if (type.unionDetails && type.unionDetails.length > 0) {
        type.unionDetails.forEach(member => analyzeType(member));
      }
    };

    // 开始递归分析
    analyzeType(structure);
    return Array.from(requiredSerializers);
  }

  private containsGenericType(structure: TypeStructure): boolean {
    // 检查当前节点是否为泛型
    if (structure.kind === PropertyKind.GENERIC) {
      return true;
    }

    // 递归检查泛型参数（如 Array<T>, Map<K,V>）
    if (structure.args) {
      return structure.args.some(arg => this.containsGenericType(arg));
    }

    // 递归检查联合类型的成员（如 T | string | number）
    if (structure.unionDetails) {
      return structure.unionDetails.some(member => this.containsGenericType(member));
    }

    return false;
  }

  private propertyAnalysisToPropertyGenerationInfo(properties: PropertyAnalysis[]): PropertyGenerationInfo[] {
    return properties.filter((prop) => {
      // 排除@Transient的属性
      if (prop.decorators?.isTransient) {
        return false;
      }
      // 容错机制：排除 UNKNOWN 类型（双保险，理论上分析阶段已强制要求有 @Transient）
      if (prop.type.kind === PropertyKind.UNKNOWN) {
        Logger.warn(`属性 ${prop.name} 类型为 UNKNOWN，已自动跳过序列化生成`);
        return false;
      }
      return true;
    }).map((prop) => {
      const handler = this.registry.getHandlerForKind(prop.type.kind);
      // ✅ 传递with参数给Handler，让Handler处理自定义序列化器
      const serializer = handler.getSerializerMetadata(prop.type, prop.decorators?.with);
      return { analysis: prop, serializer };
    });
  };

  private generateSerialNameConstant(result: ClassAnalysis | InterfaceAnalysis, context: ITaskContext): string {
    const relativePath = context.calculateSourceRootToModuleRoot(result.sourceFilePath);
    const serialName = SerializationPathUtil.join(context.getPackageName(), relativePath, result.className + '.class')
      .replaceAll(SerializationPathUtil.sep, '/');
    return result.decorators?.serialName || serialName;
  }
}